Skip to content

Native interop rewrite#13462

Open
lamek wants to merge 17 commits into
flutter:mainfrom
lamek:native-interop-rewrite
Open

Native interop rewrite#13462
lamek wants to merge 17 commits into
flutter:mainfrom
lamek:native-interop-rewrite

Conversation

@lamek

@lamek lamek commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Updates #13115

jwill and others added 8 commits February 24, 2026 20:00
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Removed placeholder for diagram and extra line breaks.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@lamek lamek requested review from a team and sfshaza2 as code owners June 5, 2026 01:10

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces comprehensive documentation and guides for direct native interop in Flutter, including new pages on using jnigen for Android, ffigen for iOS, and a comparison of platform integration options. The review feedback identifies several critical issues in the code snippets, such as a guaranteed runtime crash in the iOS FFI example due to incorrect string casting, missing configuration classes in the jnigen setup causing compilation failures, multiple JNI local reference memory leaks in the Android permissions example, duplicated Groovy dependencies, and syntax errors from missing closing braces. Addressing these issues will ensure the code examples are safe, correct, and idiomatic.

Comment thread src/content/platform-integration/ios/ffigen.md Outdated
Comment on lines +90 to +95
classes: [
// provided by Android OS
'android.os.Bundle',
'android.content.Intent',
'android.content.Context'
],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The custom SecondActivity Kotlin class is missing from the classes list in tool/jnigen.dart. Without adding it here, jnigen will not generate the Dart bindings for SecondActivity, causing the Dart compilation to fail on line 125 when referencing native.SecondActivity.type.jClass.

Suggested change
classes: [
// provided by Android OS
'android.os.Bundle',
'android.content.Intent',
'android.content.Context'
],
classes: [
// provided by Android OS
'android.os.Bundle',
'android.content.Intent',
'android.content.Context',
'com.example.android_launch_activity.SecondActivity'
],


// Context.fromReference ensures we get Android Context object
// rather than the default `JObject`
var context = native.Context.fromReference(Jni.androidApplicationContext.reference);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually accessing the low-level .reference property and calling fromReference, you can use the more idiomatic .as() extension method on JObject to cast the context to native.Context. This matches the modern style used in jnigen.md.

Suggested change
var context = native.Context.fromReference(Jni.androidApplicationContext.reference);
var context = Jni.androidApplicationContext.as(native.Context.type);

Comment thread src/content/platform-integration/ios/ffigen.md Outdated
Comment thread src/content/platform-integration/ios/ffigen.md Outdated
Comment on lines +80 to +109
int checkAndRequestPermission(
JObject context,
String permission,
Function callback,
) {
// Do I have permission?
if (ContextCompat.checkSelfPermission(context, permission.toJString()) ==
PackageManager.PERMISSION_GRANTED) {
callback();
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
Jni.androidActivity(PlatformDispatcher.instance.engineId!),
permission.toJString(),
) ==
true) {
// Has the user denied the permission before?
// Give a reason why I need the permission
// and allow a re-request
print("I should ask for permission");
// TODO Flow to show UI to reshow perms dialog
return -2;
} else {
// Ask for permission
ActivityCompat.requestPermissions(
Jni.androidActivity(PlatformDispatcher.instance.engineId!),
JArray.of(JString.type, [permission.toJString()]),
0,
);
}
return 0;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In checkAndRequestPermission, permission.toJString() is called up to three times, creating multiple JNI local references that are never released. It is much more efficient and leak-safe to convert the string once, use the variable, and release it in a finally block.

  int checkAndRequestPermission(
    JObject context,
    String permission,
    Function callback,
  ) {
    final jPermission = permission.toJString();
    try {
      // Do I have permission?
      if (ContextCompat.checkSelfPermission(context, jPermission) ==
          PackageManager.PERMISSION_GRANTED) {
        callback();
      } else if (ActivityCompat.shouldShowRequestPermissionRationale(
            Jni.androidActivity(PlatformDispatcher.instance.engineId!),
            jPermission,
          ) ==
          true) {
        // Has the user denied the permission before?
        // Give a reason why I need the permission
        // and allow a re-request
        print("I should ask for permission");
        // TODO Flow to show UI to reshow perms dialog
        return -2;
      } else {
        // Ask for permission
        ActivityCompat.requestPermissions(
          Jni.androidActivity(PlatformDispatcher.instance.engineId!),
          JArray.of(JString.type, [jPermission]),
          0,
        );
      }
      return 0;
    } finally {
      jPermission.release();
    }
  }

Comment thread sites/docs/src/content/platform-integration/android/request-permission.md Outdated
@lamek

lamek commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@jwill this is draft (v2) of the Interop rewrite.

I still need to test the ffigen tutorial for iOS.

I could use some extra attention on the table to help devs choose an Interop solution: https://github.com/flutter/website/pull/13462/changes#diff-39b4cf53fbefc7c1e7d95424eaea65acb9a711a8a0473ed816ff4474123220a6R15

@lamek lamek requested a review from jwill June 5, 2026 01:13
@flutter-website-bot

flutter-website-bot commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Visit the preview URL for this PR (updated for commit b52b94c):

https://flutter-docs-prod--pr13462-native-interop-rewrite-je6br604.web.app

@lamek

lamek commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

I'm iterating on the ffigen tutorial but I can't get the generated code to work with the example code. I might have to rework this tutorial to use a much simpler example.

@sfshaza2

sfshaza2 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Thanks for closing that old PR!!! Once the code changes have been made and approved (by both Gemini and a DRE). I'm good!

@lamek lamek force-pushed the native-interop-rewrite branch from b52b94c to ecc2329 Compare June 12, 2026 20:50
@flutter-website-bot

flutter-website-bot commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Staged preview of the updated docs.flutter.dev site (updated for commit 52f63ad):

https://flutter-docs-prod--docs-pr13462-native-interop-rewrite-wju7kso6.web.app

@flutter flutter deleted a comment from flutter-website-bot Jun 13, 2026
jwill and others added 3 commits June 12, 2026 18:09
Remove duplicated dependencies block

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@flutter-website-bot

flutter-website-bot commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Staged preview of the updated flutter.dev site (updated for commit 52f63ad):

https://flutter-dev-230821--www-pr13462-native-interop-rewrite-h2p0zkrz.web.app

jwill added 3 commits June 12, 2026 18:57
Fixed link that was preventing dash_site from checking the links.
Added redirect for the "call-jetpack-apis" page to "jnigen" and verified with check links.
It is based on the ios calendar demo in flutter/demos
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants